<?php

/*
* gestiunea sesiunilor
*/
require_once ('xmlDocument.class.php');
require_once ('xmlChapter.class.php');
require_once ('xmlChapterComment.class.php');
require_once ('xmlBasicElements.class.php');
require_once ("database.php");
require_once ("mailer.php");
require_once ("form.php");

class Session {
	public $docName;
	public $docPath;
	public $docElements=array();
	
	private $databaseHandler;
	
	//username ales la inregistrare
	public $username;
	//valoare aleatoare generata la login
	public $userid;
	//nivelul de acces al utilizatorului
	public $userlevel;
	//ora la care a fost ultima data activ(a incarcat ultima data vreo pagina); daca incepand de la aceasta ora userul este inactiv o perioada stabilita de admin-> logout
	public $time;
	//true daca userul este logat
	public $logged_in;
	//tine informatii despre utilizator
	public $userinfo = array();
	//url paginii curente pe care userul o viziteaza
	public $url;
	//url ultimii pagini vizitate de user
	//!!!da unele erori pentru anumite pagini
	public $referrer;
	//limba in care va fi afisat site-ul
	public $siteLanguage;

	//constructorul clasei
	public function __construct(& $database){
		$this->time=time();
		$this->databaseHandler=& $database;
		$this->startSession();
	}

	//initializeaza obiectul Sessin; determina daca un anumit user este logat
	//determina vizitatorii on-line
	function startSession()
	{
		$this->userid='123456';
		//se foloseste de obiectul $database, responsabil cu conexiune la bd
		//global $database;
		//deschide sesiune noua
		session_start();

		if(isset($_SESSION['docName'])){
			$this->docName=$_SESSION['docName'];
		}else{
			$_SESSION['docName']='';
		}
		if(isset($_SESSION['docPath'])){
			$this->docPath=$_SESSION['docPath'];
		}else{
			$_SESSION['docPath']='';
		}
		if(isset($_SESSION['docElements'])){
			$this->docElements=$_SESSION['docElements'];
		}else{
			$_SESSION['docElements']=array();
		}
		
		//setare limba implicita de afisare site
		if(!isset($_SESSION['siteLanguage'])){
			$this->siteLanguage=$_SESSION['siteLanguage']=SITE_DEFAULT_LANG;
		}else{
			$this->siteLanguage=$_SESSION['siteLanguage'];
		}

		//determina daca uilizatorul este logat
		$this->logged_in=$this->checkLogin();

		//stabileste nivelul de acces GUEST daca userul nu este logat
		if (!$this->logged_in){
			$this->username =$_SESSION['username']=GUEST_NAME;
			$this->userlevel=GUEST_LEVEL;
			$this->databaseHandler->addActiveGuest($_SERVER['REMOTE_ADDR'], $this->time);
		}
		//daca utilizatorul este logat, i se innoieste timestamp-ul pentru a nu eliminat pentru inactivitate
		else{
			$this->databaseHandler->addActiveUser($this->username, $this->time);
		}

		//se face refreh pe tabelele cu membrii si vizitatori inactivi, inlaturandu-i pe cei cu o perioada de inactivitate mai mare decat cea stabilita de admin
		$this->databaseHandler->removeInactiveUsers();
		$this->databaseHandler->removeInactiveGuests();

		//stabileste ultima pagina vizitata de user
		if (isset($_SESSION['url'])){
			$this->referrer=$_SESSION['url'];
		}else{
			$this->referrer="/";
		}

		//mutator pentru variabila url
		$this->url=$_SESSION['url']=$_SERVER['PHP_SELF'];
	}

	//verifica daca utilizatorul este logat deja(si implicit o sesiune cu datele sale este creata deja)
	//verifica si autenticitatea userului
	//returneaza true daca daca utilizatorul este deja logat
	function checkLogin()
	{
		//global $database;

		//verifica daca s-a ales optiunea de reamintire a logarii
		if (isset($_COOKIE['cookname']) && isset($_COOKIE['cookid']))
		{
			$this->username=$_SESSION['username']=$_COOKIE['cookname'];
			$this->userid  =$_SESSION['userid']=$_COOKIE['cookid'];
		}

		//verifica daca username si userId exista si diferit de guest
		if (isset($_SESSION['username']) && isset($_SESSION['userid']) && $_SESSION['username'] != GUEST_NAME)
		{
			//verifica daca username si userId sunt valide
			if ($this->databaseHandler->confirmUserID($_SESSION['username'], $_SESSION['userid']) != 0)
			{
				//functia confirmUserID returneaza 0 daca userul este in bd si userId-urile se potrivesc
				unset($_SESSION['username']);
				unset($_SESSION['userid']);
				return false;
			}

			//userul este logat, deci se pot seta variabilele corespunzatoare din clasa
			$this->userinfo =$this->databaseHandler->getUserInfo($_SESSION['username']);
			$this->username =$this->userinfo['username'];
			$this->userid   =$this->userinfo['userid'];
			$this->userlevel=$this->userinfo['userlevel'];
			return true;
		}
		//userul nu este logat
		else
		{
			return false;
		}
	}

	//verifica daca datele transmise de user prin formul de logare sunt adevarate prin confruntare cu bd si face logarea userului
	function login($subuser, $subpass, $subremember)
	{
		//se folosesc obiectele $database-pt conexiune la bd, si form- pt preluarea datelor transmise de user
		$form=new Form();

		//verificare camp user din formul login
		$field="user";
		//verifica daca acest camp este gol, si stabileste eroarea
		if (!$subuser || strlen($subuser=trim($subuser)) == 0)
		{
			$form->setError($field, "* Username not entered");
		}
		//daca acest camp nu este gol, verifica sa nu contina doar cifre
		else
		{
			if (!eregi("^([0-9a-z])*$", $subuser))
			{
				$form->setError($field, "* Username not alphanumeric");
			}
		}

		//verificare camp password din formul login
		$field="pass";

		//verifica daca acest camp este gol, si stabileste eroarea
		if (!$subpass)
		{
			$form->setError($field, "* Password not entered");
		}

		//se opreste executia daca exista erori in datele furnizate de user
		if ($form->num_errors > 0)
		{
			$_SESSION['error_array']=$form->getErrorArray();
			return false;
		}

		$subuser=stripslashes($subuser);
		//verifica daca userul este inregistrat si parola este corecta
		$result =$this->databaseHandler->confirmUserPass($subuser, md5($subpass));

		//verificare coduri de eroare
		//functia confirmUserPass returneaza 1 daca username nu este gasit in bd si 2 daca parola este incorecta
		if ($result == 1)
		{
			$field="user";
			$form->setError($field, "* Username not found");
		}
		else if ($result == 2)
		{
			$field="pass";
			$form->setError($field, "* Invalid password");
		}

		//se opreste executia daca exista erori
		if ($form->num_errors > 0)
		{
			$_SESSION['error_array']=$form->getErrorArray();
			return false;
		}

		//username si parola corecte, deci putem seta variabilele in sesiunea deschisa
		session_regenerate_id();
		$this->userinfo =$this->databaseHandler->getUserInfo($subuser);
		$this->username =$_SESSION['username']=$this->userinfo['username'];
		$this->userid   =$_SESSION['userid']=$this->generateRandID();
		$this->userlevel=$this->userinfo['userlevel'];

		//inserare userId in bd si update tabela cu useri activi
		$this->databaseHandler->updateUserField($this->username, "userid", $this->userid);
		$this->databaseHandler->addActiveUser($this->username, $this->time);
		$this->databaseHandler->removeActiveGuest($_SERVER['REMOTE_ADDR']);

		//daca userul a optat ca sa fie "retinut" de site, se seteaza 2 cookie-uri: una cu username-ul sau si una cu userId generat aleator
		//variabilele cookie expira dupa o perioada stabilita de admin
		//daca userul nu a accessat Logout la ultima sa vizita, la urmatoarea intoarcere este logat automat :)
		if ($subremember)
		{
			setcookie("cookname", $this->username, time() + COOKIE_EXPIRE, COOKIE_PATH);
			setcookie("cookid", $this->userid, time() + COOKIE_EXPIRE, COOKIE_PATH);
		}

		//succes
		return true;
	}

	//sterge variabilele cookie de pe calculatorul userului si datele din variabila de tip sesiune; noul sau nivel de acces este de guest
	function logout()
	{
		//global $database;

		//stergere cookie(stabilire timpul de expirare in trecut)
		if (isset($_COOKIE['cookname']) && isset($_COOKIE['cookid']))
		{
			setcookie("cookname", "", time() - COOKIE_EXPIRE, COOKIE_PATH);
			setcookie("cookid", "", time() - COOKIE_EXPIRE, COOKIE_PATH);
		}

		//stergere date din variabila de tip sesiune
		unset($_SESSION['username']);
		unset($_SESSION['userid']);

		//modificare in variabila din clasa care reflecta faptul ca userul nu mai este logat
		$this->logged_in=false;

		//stergere userul din tabela de membrii activi si adaugare in tabela de vizitatori on-line
		$this->databaseHandler->removeActiveUser($this->username);
		$this->databaseHandler->addActiveGuest($_SERVER['REMOTE_ADDR'], $this->time);

		//setare nivel acces guest
		$this->username =GUEST_NAME;
		$this->userlevel=GUEST_LEVEL;
	}

	//apelata cand utilizatorul trimite formul de inregistrare
	//returneaza 2 pentru esec, 1 pentru eroari de completare a formului, 0 pentru succes
	function register($subuser, $subpass, $subemail)
	{
		///global $form, $mailer;
		$form=new Form();
		$mailer=new Mailer();

		//verifica daca acest camp este completat si seteaza eroarea corespunzatoare
		$field="reguser";

		if (!$subuser || strlen($subuser=trim($subuser)) == 0)
		{
			$form->setError($field, "Username not entered");
		}
		else
		{
			//username-ul trebuie sa fie de minim 5 si max 30 caractere
			$subuser=stripslashes($subuser);

			if (strlen($subuser) < 5)
			{
				$form->setError($field, "Username below 5 characters");
			}
			else if (strlen($subuser) > 30)
			{
				$form->setError($field, "Username above 30 characters");
			}
			//verifica daca username-ul nu este un numar
			else if (!eregi("^([0-9a-z])+$", $subuser))
			{
				$form->setError($field, "Username not alphanumeric");
			}
			//verifica daca username-ul ales nu este un cuvant rezervat
			else if (strcasecmp($subuser, GUEST_NAME) == 0)
			{
				$form->setError($field, "Username reserved word");
			}
			//verifica daca username-ul nu este folosit deja de alt utilizator inregistrat
			else if ($this->databaseHandler->usernameTaken($subuser))
			{
				$form->setError($field, "Username already in use");
			}
			//verifica daca username-ul nu este restrictionat
			else if ($this->databaseHandler->usernameBanned($subuser))
			{
				$form->setError($field, "Username banned");
			}
		}

		//verificare parola
		$field="regpass";

		//campul nu este completat
		if (!$subpass)
		{
			$form->setError($field, "Password not entered");
		}
		else
		{
			//parola trebuie sa fie de minim 4 caractere
			$subpass=stripslashes($subpass);

			if (strlen($subpass) < 4)
			{
				$form->setError($field, "Password too short");
			}
			//verifica parola sa nu fie numar
			else if (!eregi("^([0-9a-z])+$", ($subpass=trim($subpass))))
			{
				$form->setError($field, "Password not alphanumeric");
			}
		}

		//verificare corectitudine e-mail
		$field="regemail";

		//verifica daca acest camp a fost completat
		if (!$subemail || strlen($subemail=trim($subemail)) == 0)
		{
			$form->setError($field, "Email not entered");
		}
		else
		{
			//verificare validitate e-mail
			$regex="^[_+a-z0-9-]+(\.[_+a-z0-9-]+)*" . "@[a-z0-9-]+(\.[a-z0-9-]{1,})*" . "\.([a-z]{2,}){1}$";

			if (!eregi($regex, $subemail))
			{
				$form->setError($field, "Email invalid");
			}

			$subemail=stripslashes($subemail);
		}

		//intrerupe proces daca exista erori
		if ($form->num_errors > 0)
		{
			$_SESSION['error_array']=$form->getErrorArray();
			return 1;
		}
		//daca nu exista erori, adauga datele in bd si trimite mail
		else
		{
			if ($this->databaseHandler->addNewUser($subuser, md5($subpass), $subemail))
			{
				if (EMAIL_WELCOME)
				{
					$mailer->sendWelcome($subuser, $subemail, $subpass);
				}

				//succes
				return 0;
			}
			else
			{
				//eroare, nu au fost introduse datele in bd
				return 2;
			}
		}
	}

	//modificare date cont personal
	function editAccount($subcurpass, $subnewpass, $subemail)
	{
		global $form;

		//verificare parola curenta
		if ($subnewpass)
		{
			//verifica daca acest camp a fost completat
			$field="curpass";

			if (!$subcurpass)
			{
				$form->setError($field, "* Current Password not entered");
			}
			else
			{
				//verifica daca parola nu este prea scurta sau e un numar
				$subcurpass=stripslashes($subcurpass);

				if (strlen($subcurpass) < 4 || !eregi("^([0-9a-z])+$", ($subcurpass=trim($subcurpass))))
				{
					$form->setError($field, "* Current Password incorrect");
				}

				//verifica daca parola este corecta
				if ($this->databaseHandler->confirmUserPass($this->username, md5($subcurpass)) != 0)
				{
					$form->setError($field, "* Current Password incorrect");
				}
			}

			//verificare parola noua
			$field  ="newpass";
			//verifica lungime
			$subpass=stripslashes($subnewpass);

			if (strlen($subnewpass) < 4)
			{
				$form->setError($field, "* New Password too short");
			}
			//verifica daca nu e numar
			else if (!eregi("^([0-9a-z])+$", ($subnewpass=trim($subnewpass))))
			{
				$form->setError($field, "* New Password not alphanumeric");
			}
		}
		//raportare eventuale erori
		else if ($subcurpass)
		{
			$field="newpass";
			$form->setError($field, "* New Password not entered");
		}

		//verificare email nou
		$field="email";

		if ($subemail && strlen($subemail=trim($subemail)) > 0)
		{
			//verifica validitatea formatului adresei
			$regex="^[_+a-z0-9-]+(\.[_+a-z0-9-]+)*" . "@[a-z0-9-]+(\.[a-z0-9-]{1,})*" . "\.([a-z]{2,}){1}$";

			if (!eregi($regex, $subemail))
			{
				$form->setError($field, "* Email invalid");
			}

			$subemail=stripslashes($subemail);
		}

		//raportare eventuale erori si oprire proces
		if ($form->num_errors > 0)
		{
			return false;
		}

		//neexistand erori, se face update pentru parola
		if ($subcurpass && $subnewpass)
		{
			$this->databaseHandler->updateUserField($this->username, "password", md5($subnewpass));
		}

		//se schimba email-ul
		if ($subemail)
		{
			$this->databaseHandler->updateUserField($this->username, "email", $subemail);
		}

		//succes
		return true;
	}

	//verifica daca userul care s-a logat este admin sau nu; returneaza true daca da
	function isAdmin() { return ($this->userlevel == ADMIN_LEVEL || $this->username == ADMIN_NAME); }

	//genereaza userId(rezultatul aplicarii functiei md5 unui string format din cifre si litere)
	function generateRandID() { return md5($this->generateRandStr(16)); }

	//genereaza un string format din cifre si litere folosit de functia generateRandID()
	function generateRandStr($length)
	{
		$randstr="";

		for ($i=0; $i < $length; $i++)
		{
			$randnum = mt_rand(0, 61);

			if ($randnum < 10)
			{
				$randstr.=chr($randnum + 48);
			}
			else if ($randnum < 36)
			{
				$randstr.=chr($randnum + 55);
			}
			else
			{
				$randstr.=chr($randnum + 61);
			}
		}

		return $randstr;
	}

	//funcrie setare limba afisare site
	function setSiteLanguage($lang)
	{
		$_SESSION['siteLanguage']=$lang;
	}

	public function createNewDocument($name, $path) {
		$this->docName=$_SESSION['docName']=$name;
		$this->docPath=$_SESSION['docPath']=$path;
	}

	public function createNewChapter($name){
		$this->docElements[]=$_SESSION['docElements'][]=$name;
	}
	
	public function setActiveProjects($projects){
		$_SESSION['activeProjects']=$projects;
	}

}

///$Session=new session();
?>